package com.github.mongobee.dao; import static com.github.mongobee.changeset.ChangeEntry.CHANGELOG_COLLECTION; import static org.springframework.util.StringUtils.hasText; import org.bson.Document; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.mongobee.changeset.ChangeEntry; import com.github.mongobee.exception.MongobeeConfigurationException; import com.github.mongobee.exception.MongobeeConnectionException; import com.mongodb.DB; import com.mongodb.MongoClient; import com.mongodb.MongoClientURI; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; /** * @author lstolowski * @since 27/07/2014 */ public class ChangeEntryDao { private static final Logger logger = LoggerFactory.getLogger("Mongobee dao"); private MongoDatabase mongoDatabase; private DB db; // only for Jongo driver compatibility - do not use in other contexts private MongoClient mongoClient; private ChangeEntryIndexDao indexDao = new ChangeEntryIndexDao(); private LockDao lockDao = new LockDao(); public MongoDatabase getMongoDatabase() { return mongoDatabase; } /** * @deprecated implemented only for Jongo driver compatibility and backward compatibility - do not use in other contexts * @return com.mongodb.DB */ public DB getDb() { return db; } public MongoDatabase connectMongoDb(MongoClient mongo, String dbName) throws MongobeeConfigurationException { if (!hasText(dbName)) { throw new MongobeeConfigurationException("DB name is not set. Should be defined in MongoDB URI or via setter"); } else { this.mongoClient = mongo; db = mongo.getDB(dbName); // for Jongo driver and backward compatibility (constructor has required parameter Jongo(DB) ) mongoDatabase = mongo.getDatabase(dbName); ensureChangeLogCollectionIndex(mongoDatabase.getCollection(CHANGELOG_COLLECTION)); initializeLock(); return mongoDatabase; } } public MongoDatabase connectMongoDb(MongoClientURI mongoClientURI, String dbName) throws MongobeeConfigurationException, MongobeeConnectionException { final MongoClient mongoClient = new MongoClient(mongoClientURI); final String database = (!hasText(dbName)) ? mongoClientURI.getDatabase() : dbName; return this.connectMongoDb(mongoClient, database); } /** * Try to acquire process lock * * @return true if successfully acquired, false otherwise * @throws MongobeeConnectionException exception */ public boolean acquireProcessLock() throws MongobeeConnectionException { verifyDbConnection(); return lockDao.acquireLock(getMongoDatabase()); } public void releaseProcessLock() throws MongobeeConnectionException { verifyDbConnection(); lockDao.releaseLock(getMongoDatabase()); } public boolean isProccessLockHeld() throws MongobeeConnectionException { verifyDbConnection(); return lockDao.isLockHeld(getMongoDatabase()); } public boolean isNewChange(ChangeEntry changeEntry) throws MongobeeConnectionException { verifyDbConnection(); MongoCollection<Document> mongobeeChangeLog = getMongoDatabase().getCollection(CHANGELOG_COLLECTION); Document entry = mongobeeChangeLog.find(changeEntry.buildSearchQueryDBObject()).first(); return entry == null; } public void save(ChangeEntry changeEntry) throws MongobeeConnectionException { verifyDbConnection(); MongoCollection<Document> mongobeeLog = getMongoDatabase().getCollection(CHANGELOG_COLLECTION); mongobeeLog.insertOne(changeEntry.buildFullDBObject()); } private void verifyDbConnection() throws MongobeeConnectionException { if (getMongoDatabase() == null) { throw new MongobeeConnectionException("Database is not connected. Mongobee has thrown an unexpected error", new NullPointerException()); } } private void ensureChangeLogCollectionIndex(MongoCollection<Document> collection) { Document index = indexDao.findRequiredChangeAndAuthorIndex(mongoDatabase); if (index == null) { indexDao.createRequiredUniqueIndex(collection); logger.debug("Index in collection " + CHANGELOG_COLLECTION + " was created"); } else if (!indexDao.isUnique(index)) { indexDao.dropIndex(collection, index); indexDao.createRequiredUniqueIndex(collection); logger.debug("Index in collection " + CHANGELOG_COLLECTION + " was recreated"); } } public void close() { this.mongoClient.close(); } private void initializeLock() { lockDao.intitializeLock(mongoDatabase); } /* Visible for testing */ void setIndexDao(ChangeEntryIndexDao changeEntryIndexDao) { this.indexDao = changeEntryIndexDao; } /* Visible for testing */ void setLockDao(LockDao lockDao) { this.lockDao = lockDao; } }